home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / varlnsrc.arc / VARLINT.C < prev    next >
C/C++ Source or Header  |  1988-07-14  |  10KB  |  424 lines

  1. /*###########################################################################
  2.  *
  3.  *    This program is used to find those pesty errors in varags type
  4.  *    functions such as printf.  It only handles those functions defined
  5.  *    in the structure"fu".
  6.  *
  7.  *      By Daniel B. Suthers Mar 3, 1988
  8.  *
  9.  *      Copyright 1988 by Daniel B. Suthers, Concord, California, USA.
  10.  *      License is granted to distribute this program at will, as long as
  11.  *      the source is also provided free of charge to anyone who recieves
  12.  *      the binaries, or to anyone who wants it,
  13.  *    AND all copyright notices are left intact.
  14.  *    The 
  15.  *
  16. ###move $This_File 755 uprog none /uprog/bin/src/varlint.c
  17. ##move $This_File 755 uprog none /usr/uprog/src/bin/varlint.c
  18.  *#########################################################################*/
  19. #include <stdio.h>
  20. #include <ctype.h>
  21.  
  22. #define VER "2.7"
  23. #define MAX 512
  24. #define NUMNAMES 6
  25.  
  26. #ifdef pdp11
  27. char APPL[] ="\n##move $This_File 755 uprog none /usr/uprog/bin/varlint\n";
  28. #else
  29. char APPL[]="\n###move $This_File 755 uprog none /usr/lbin/varlint\n";
  30. FILE *fopen();
  31. void scandoos();
  32. #endif
  33.  
  34. struct funcdat{
  35.     char nam[9];                /* stores function names*/
  36.     int len;                /* number of chars in names*/
  37.     int pos;                /* position of control string*/
  38.     int scan;
  39.     };
  40.  
  41. struct funcdat fu[ NUMNAMES] = {
  42.     { "printf", 6, 0, 0},
  43.     { "scanf",  5, 0, 1},
  44.     { "sprintf", 7,1, 0},
  45.     { "sscanf", 6, 1, 1},
  46.     { "fprintf", 7,1, 0},
  47.     { "fscanf", 6, 1, 1}
  48.     };
  49.  
  50. char *fgets(), *findname();
  51. int in_comment = 0;                /* flag = 1 when in a comment*/
  52.  
  53. main(argc, argv, env)
  54. int argc;
  55. char *argv[], *env[];
  56. {
  57.   extern int optind;
  58.   extern char *optarg;
  59.   register int inta;
  60.   char filename[128];
  61.   FILE *infile ;
  62.  
  63.   while( (inta = getopt( argc, argv, "vVhH")) != EOF)
  64.   {
  65.     switch (inta)
  66.     {
  67.       case 'V':
  68.       case 'v':
  69.     fprintf (stderr, "%s\n"
  70.     , VER);
  71.     return(0);
  72.       case 'h':
  73.       case 'H':
  74.     help();
  75.     return(0);
  76.       default:
  77.     printf("Bad argument\nTry -h for help.\n");
  78.     return(1);
  79.     }
  80.   }
  81.   while( optind < argc )                        /* these would be files*/
  82.   {
  83.     strcpy(filename, argv[optind++]);
  84.     if( (infile = fopen(filename, "r") ) == NULL)
  85.     {
  86.       fprintf(stderr, "Unable to open source file %s\n", filename);
  87.     }
  88.     else
  89.     {
  90.       printf("Working on %s\n", filename);
  91.       scandoos(infile);
  92.       if( infile != (FILE *) NULL)
  93.     fclose(infile);
  94.     }
  95.   }
  96. return(0);
  97. }                        /*end of main*/
  98.  
  99. help()
  100. {
  101.   printf(
  102.     "\n\tCopyright 1988 by Daniel B. Suthers, Concord, California, USA.\n");
  103.   printf(
  104.     "\tLicense is granted to distribute this program at will, as long as\n");
  105.   printf(
  106.     "\tthe source is also provided free of charge to anyone who recieves\n");
  107.   printf("\tthe binaries, or to anyone who wants it,\n");
  108.   printf("\tAND all copyright notices are left intact.\n");
  109.   printf("\n\tThis program checks for mismatched arguments in functions\n");
  110.   printf("\tthat accept variable arguments ala printf().\n");
  111.   printf("\tCurrently supports: printf, scanf and their cousins.\n");
  112.   printf("\t(Checks only for # of args and & for integers)\n");
  113.   printf("\n\tThe arguments accepted are:\n\n");
  114.   printf("\t-v\tPrint the version number and exit.\n");
  115.   printf("\t-help\tPrint the most current help.\n");
  116. return(0);
  117. }
  118.  
  119. #ifdef u3b5
  120. void
  121. #endif
  122. scandoos(infile)
  123. FILE *infile;
  124. {
  125.   register int linenum, reterr, oldline;
  126.   char buff[MAX*3], *buffp;            /* allow 10 lines */
  127.   char tempstr[MAX*3];
  128.   int funcindex;
  129.   
  130.   linenum = oldline = 0;
  131.   reterr = 0;
  132.   while( fgets(buff, MAX, infile) != (char *)NULL )
  133.   {
  134.     if(reterr == 100 )                /* multi line statement */
  135.     {
  136.       if( oldline == 0)
  137.         oldline = linenum;
  138.       strcat(tempstr,buff);
  139.       strcpy(buff, tempstr);
  140.       reterr = 0;
  141.     }
  142.     linenum++;
  143.     if( (buffp = findname(buff,&funcindex)) == NULL )
  144.       continue;
  145.     if( in_comment )
  146.       continue;
  147.     /*
  148.     printf("%4d: %s",linenum, buffp);
  149.     */
  150.     if( (reterr = parsedo(buffp,funcindex)) > 0)
  151.     {
  152.       if( reterr < 100 )
  153.       {
  154.     if( oldline != 0)
  155.     {
  156.       printf("***** Error at line %5d\n%s", oldline, buffp);
  157.       oldline = 0;
  158.     }
  159.     else
  160.       printf("***** Error at line %5d\n%s", linenum, buffp);
  161.       }
  162.       switch(reterr)
  163.       {
  164.     case 1:
  165.       printf("More \"%%\" in control string than there are variables.\n\n");
  166.       break;
  167.     case 2:
  168.       printf("A varible type did not match the \"%%\".\n\n");
  169.       break;
  170.     case 3:
  171.       printf("An undefined variable used.\n\n");
  172.       break;
  173.     case 4: 
  174.       printf("An un-recognized construct, might be ok.\n\n");
  175.       break;
  176.     case 5:
  177.       printf("Fewer \"%%\" in control string than there are variables.\n\n");
  178.       break;
  179.     case 6:
  180.       printf("Integer type requires an ampersand (\&).\n\n");
  181.       break;
  182.     case 7:
  183.       printf("Print found a string, expecting an int.\n\n");
  184.       break;
  185.     case 8:
  186.       printf("Unknown %% specifier.\n\n");
  187.       break;
  188.     case 9:
  189.       printf("Re declaration of the function. You sure this is ok?\n\n");
  190.       break;
  191.     case 10:
  192.       printf("Null control string. You sure this is ok?\n\n");
  193.       break;
  194.     case 100:
  195.       strcpy( tempstr, buff);
  196.       break;
  197.       }
  198.     }                        /* end of if(parsedo) */
  199.     else
  200.       oldline = 0;
  201.   }     
  202. }                        /* end of scandoos() */
  203.  
  204. char *
  205. findname(string, funcind)
  206. char string[];
  207. int *funcind;
  208. {
  209.   char *ptr;
  210.   register int a;
  211.  
  212.   ptr = string;
  213.   while( *ptr != NULL )
  214.   {
  215.     if( *ptr == '/')                /* set flag if this */
  216.       if( *(ptr + 1) == '*')            /* is start of comment*/
  217.       {
  218.     in_comment = 1;
  219.     ptr += 2;
  220.     continue;
  221.       }
  222.     if( *ptr == '*' )                /* un-set flag if end */
  223.       if( *(ptr+1) == '/')                /* of comment         */
  224.       {
  225.     in_comment = 0;
  226.     ptr +=2;
  227.     continue;
  228.       }
  229.     for( a = 0; a < NUMNAMES; a++)
  230.     {
  231.       if( strncmp( ptr, fu[a].nam, fu[a].len ) == 0 )
  232.       {
  233.     *funcind = a;
  234.     return(ptr);
  235.       }
  236.     }
  237.     ptr++;
  238.   }
  239. return(NULL);
  240. }
  241.  
  242. int
  243. parsedo(buff, fi)
  244. char buff[];                    /* function string */
  245. int fi;                        /* fu.[] index */
  246. {
  247.   register int parens, pcntnum, c;
  248.   char *buffp;
  249.   int end=0, inquotes = 0;
  250.   int vartype[124];                /* for var type */
  251.  
  252.   parens = 0;
  253.   buffp = buff;
  254.   buffp += fu[fi].len;                 /* get past function */
  255.   while( isspace(*buffp) )            /* skip white space  */
  256.     buffp++;
  257.   if( *buffp == NULL)
  258.     return(100);
  259.   if( *buffp != '(' )                /* not a function */
  260.     return(0);
  261.   if( *(buffp +1) == ')' )            /* function definition */
  262.     return(9);
  263.   buffp++;
  264.   while( isspace(*buffp) )            /* skip white space  */
  265.     buffp++;
  266.   if( *buffp == NULL)
  267.     return(100);
  268.   for(c = 0;c < fu[fi].pos; c++)        /* skip to control string*/
  269.   {                              /* (stop on comma) */
  270.     while( (*buffp != NULL) && (*buffp != ',') )
  271.     buffp++;
  272.     if( *buffp == NULL)
  273.       return(100);
  274.     buffp++;
  275.   }
  276.   if( *buffp == NULL)
  277.     return(100);
  278.   while( isspace( *(buffp)) )         /* for ' , "test"'   */
  279.     buffp++;
  280.   if( *buffp == NULL)
  281.     return(100);
  282.   if( *buffp != '"')                /* should be on first quote*/
  283.     return(4);
  284.   if( *(buffp+1) == '"')            /* dont want "" as cntl str */
  285.     return(10);
  286.                         /* count the percent signs */
  287.                         /* starting on first quote */
  288.   pcntnum = 0;
  289.   end = 0;
  290.   while( *buffp++ != NULL )
  291.   {
  292.     switch(*buffp)
  293.     {
  294.     case '"':
  295.       if( *(buffp-1) != '\\')        /*    \" is not end   */
  296.         end = 1;
  297.       else if( *(buffp-2) == '\\')        /*    \\"  is end     */
  298.         end = 1;
  299.       break;
  300.     case '%':
  301.       if( *(buffp-1) != '%')
  302.         pcntnum++;
  303.       else
  304.       {
  305.         pcntnum--;                /* delete first % of pair */
  306.         continue;
  307.       }
  308.       if( *(buffp+1) == '*' )
  309.       {
  310.         if(  fu[fi].scan == 1)
  311.         {
  312.           pcntnum--;            /* no matching variable */ 
  313.         }
  314.         else
  315.         {
  316.           pcntnum++;
  317.         }
  318.       }
  319.                         /*######################
  320.                         # load array with var type
  321.                         ######################*/
  322.                         /* throw away justification*/
  323.       if( *(buffp +1 ) == '-' || *(buffp +1) == '+')
  324.         buffp++;
  325.                           /* remove blanks and sharps */
  326.           while( isspace( *(buffp + 1)) || *(buffp + 1) == '#' ) 
  327.             buffp++;
  328.                         /* throw away size spec */
  329.       while( isdigit(*(buffp+1)) || *(buffp+1) == '.' )
  330.         buffp++;
  331.       switch (*(buffp + 1) )        /* look at next char for type */
  332.       {
  333.         case 's':
  334.         case '[':
  335.         case 'c':
  336.           vartype[pcntnum] = 's';
  337.           break;
  338.         case 'd':
  339.         case 'l':
  340.         case 'h':
  341.         case 'i':
  342.